package com.itheima.case2.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class SqlSessionUtil {

    private static SqlSessionFactory factory;

    static {
        //实例化工厂建造类
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //读取核心配置文件
        try (InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml")) {
            //创建工厂对象
            factory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到会话对象
     *
     * @return 会话对象 : 自动提交事务
     */
    public static SqlSession getSession() {
        return factory.openSession(true);
    }

    /**
     * 得到会话对象
     *
     * @param isAutoCommit 是否自动提交事务
     */
    public static SqlSession getSession(boolean isAutoCommit) {
        return factory.openSession(isAutoCommit);
    }

    /*
     *   提交事务并关闭session
     * */
    public static void commitAndClose(SqlSession session) {
        if (session != null) {
            session.commit();
            session.close();
        }
    }

    /*
     *   回滚事务并关闭session
     * */
    public static void rollbackAndClose(SqlSession session) {
        if (session != null) {
            session.rollback();
            session.close();
        }
    }

//获取mapper的代理对象,从而对mapper的方法做增强
//方法参数clazz表示方法getMapper(UserMapper.class)的参数UserMapper.class
//    public static Object getProxyMapper(Class clazz) {//Class clazz = UserMapper.class
public static <T> T getProxyMapper(Class<T> clazz) {//Class clazz = UserMapper.class


    /**
     * 参数1:类加载器,一般被代理对象的类加载器
     * 参数2:接口,被代理对象实现的结构
     * 参数3:调用处理器,处理UserMapper接口的增强方法，findUserByPage findAllUserCount等
     */
    ClassLoader classLoader = clazz.getClassLoader();
    Class<?>[] interfaces = {clazz};//{UserMapper.class}
    T proxyMapper = (T)Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
        /*
            参数：
                method ：UserMapper接口的方法findUserByPage findAllUserCount等
                args：UserMapper接口的方法findUserByPage findAllUserCount等的参数
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            //调用工具类SqlSessionUtil中的方法获取会话SqlSession对象
            SqlSession session = getSession();
            //获取原来的mapper对象
            T mapper = session.getMapper(clazz);

            //1.执行原有功能：findUserByPage findAllUserCount等
            //res表示原来方法findUserByPage findAllUserCount的返回值
            Object res = method.invoke(mapper, args);


            //2.释放资源
            session.close();
            //返回给findUserByPage findAllUserCount的调用者
            return res;
        }
    });
    //返回UserMapper接口代理对象
    return proxyMapper;
}}